/*******************************************************************\
*	file: 		ATPSendRequest.c									*
*	version:	1.06§												*
* 																	*
* Send a message to the listener whose entity name is provided by 	*
* caller.															*
* -----------------------------------------------------------------	*
* By:	Donald Koscheka, Greg Kimberly								*
* By:	Greg Kimberly, Donald Koscheka								*
* Date:	24-Sept-87													*
* ©	Copyright 1987, Apple Computer, Inc.							*
*	All Rights Reserved												*
*																	*
* -----------------------------------------------------------------	*
*						Modification History						*
* -----------------------------------------------------------------	*
*  Date	   	| By	|	 				Description					*
* -----------------------------------------------------------------	*
* 9/24/87	| GK	| file created									*
* 10/6/87	| DK	| added retry count and interval as parameters.	*
*  5-Nov-87	| DK	| added return result							*
*  3-Dec-87	| DK	| check to see whether node is a client and 	*
*			|		| terminate if not								*
*  7-Dec-87	| DK	| removed the confirm before each request.		*
* 11-Dec-87	| DK	| Set default retry count to 0.					*
*			|		| Don't send if no message specified...			*
* 21-Dec-87	| DK	| set response method to nil if not used		*
* 14-Jan-88	| DK	| modified to reflect decoupling of ATP & NBP	*
* 22-Feb-88 | DK	| Move all locked handles high					*
* -----------------------------------------------------------------	*
\*******************************************************************/

/*******************************************************************\
							Build Sequence
	
C -q2 -g -o "{hpo}"ATPSendRequest.c.o "{atp}"ATPSendRequest.c
	link  -sn Main=ATPSendRequest -sn STDIO=ATPSendRequest ¶
		 -sn INTENV=ATPSendRequest -rt XCMD=306 ¶
		 -m ATPSendRequest ¶
		 "{hpo}"ATPSendRequest.c.o "{hpo}"atalkxcmd.c.o "{hpo}"xcmdutils.c.o ¶
		 "{CLibraries}"CInterface.o ¶
		 "{Libraries}"Interface.o ¶
		 -o "{hp}"HyperPeople

\*******************************************************************/

#include <Types.h>
#include <Memory.h>
#include <Resources.h>
#include <OSUtils.h>
#include <appleTalk.h>
#include <HyperXCmd.h>
#include <atalkXCMD.h>
#include <XCMDUtils.h>

char *GetNextName();


pascal void ATPSendRequest( paramPtr )
	XCmdBlockPtr	paramPtr;
/**********************************
* ATRequest - send a request to the 
* node specified by entityName.  If a 
* response message is given, the response
* data is appended to it and hypercard is 
* called back with the response.
*
* In:	ParamPtr->params[0] = list of names to send to
*		ParamPtr->params[1] = message
*		ParamPtr->params[2] = response message 
*		ParamPtr->params[3] = number of retries
*		ParamPtr->params[4] = interval between retries
*
* Out:	Request message sent asynchronously 
*		to the server
*
**********************************/
{
	ATPBlock	*atp;
	NBPBlock	*nbp;
	short		nextentity 	= 1;
	short		found 		= 0;
	short		c, intv;
	short		result;
	short		mlen;
	char		*theData; 
	Handle		rmess		= nil;
	char 		str[32];
	char		*currentName, *nextName;
	EntityName 	eName;
	AddrBlock 	eAddr;	
	
	atp = (ATPBlock *)RetrieveHandle( paramPtr, GLOBALATPDATA );
	nbp = (NBPBlock *)RetrieveHandle( paramPtr, GLOBALNBPDATA );

	if( !atp || !nbp ){
		paramPtr->returnValue = ErrorReturn( DEFAULT_ERROR );
		return;
	}
	
	if( !atp->Client ){
		paramPtr->returnValue = ErrorReturn( DEFAULT_ERROR );
		return;
	}
	
	if( !paramPtr->params[ 0 ] ){
		paramPtr->returnValue = ErrorReturn( DEFAULT_ERROR );
		return;
	}
	
	if( paramPtr->params[ 1 ] )		/*** was a message specified ??? ***/
		mlen = slength(*(paramPtr->params[1]) );
	else{
		paramPtr->returnValue = ErrorReturn( DEFAULT_ERROR );
		return;
	}
	
	MoveHHi( paramPtr->params[0] );
	HLock( paramPtr->params[0] );

	if( paramPtr->params[2] != nil ){
		rmess = paramPtr->params[2];
		if( !**rmess )
			rmess = nil;				/*** treat empties as nils				***/
	}
		
	if( paramPtr->params[3] != nil ){
		MoveHHi( paramPtr->params[3] );
		HLock( paramPtr->params[3] );
		c2pstr( *(paramPtr->params[3] ));
		c = (short)StrToNum( paramPtr, *(paramPtr->params[3]) );
		HUnlock( paramPtr->params[3] );
	}
	else
		c = 0;	
	
	if( paramPtr->params[4] != nil ){
		MoveHHi( paramPtr->params[4] );
		HLock( paramPtr->params[4] );
		c2pstr( *(paramPtr->params[4] ));	
		intv = (short)StrToNum( paramPtr, *(paramPtr->params[4]) );
		HUnlock( paramPtr->params[4] );
	}
	else
		intv = 0;

	nextName = *(paramPtr->params[0]);	/*** point to the first name in  list 	***/
	while( currentName = nextName ){	/*** repeat for all names in the list 	***/		
		nextName = GetNextName( nextName );
		found = 0;
		nextentity = 1;
		/*** scan names list until we find a match or scan past all entities.	***/
		while( !found ){
		 	found = ExtractName( nbp, nextentity, &eName, &eAddr );
		 	if( found == 1 ){
		 		pStrCopy( &(eName.objStr), str ); /*** need to keep tuple intact***/
				p2cstr( str );
				if( !strCMP(  currentName , str ) ){
					MoveHHi( paramPtr->params[1] );
					HLock( paramPtr->params[1] );
					theData = *(paramPtr->params[1]);
					currentName = (char *)str;

					result = Request( atp, theData, mlen, &eAddr, rmess,c, intv );
					HUnlock( paramPtr->params[1] );
				}
				else{
					found = 0;
					++nextentity;
				}
			}
		} 
	} /*** while nextName ***/
	
	HUnlock( paramPtr->params[0] );
	paramPtr->returnValue = ErrorReturn( result );
}


char *GetNextName( theList )
	char	*theList;
/****************************
* Given a pointer to a list of \r 
* terminated names, replace the terminator
* with \0 and point to the character after
* the last \r found (leapfrog string).
*
* returns nil when last name is found.
*
***************************/
{	
	if( *theList == '\0' )
		return( nil );

	while( ( *theList != '\n' ) && ( *theList != '\0' ) )
		theList++;

	if( *theList == '\n' ){
		*theList = '\0';
		++theList;		/*** move to next string in the list 	***/
		return( theList );
	}
}

